#include "n32g031.h"
#include "stdint.h"
#include "stdio.h"
#include "DevicesDelay.h"
#include "DevicesSoftIIC.h"
#include "qmp6989.h"
#include "Devices6988.h"


static const int32_t QMP6989_POWER_SCALE[] = {1, 10, 100, 1000};
static const float QMP6989_CALIB_SCALE_FACTOR[] = {
    1.0E+00,
    1.0E-05,
    1.0E-10,
    1.0E-05,
    1.0E-10,
    1.0E-15,
    1.0E-12,
    1.0E-17,
    1.0E-21
};


QMP6989Type g_typeQMP6989Info = {0};


int8_t c6988Init(void)
{
    uint8_t ucConfig[18] = {0};
    int8_t cError = 0;

    vSoftIIC6998Init();

    c6988SoftReset();
    vDelayMs(1000);

    cError = cSoftIIC6998ReadDatas(IIC_6989_IC_ADDR, QMP6989_REG_PID, &g_typeQMP6989Info.pid, 1);
    /* 检查PID值是否正确 */
    if(g_typeQMP6989Info.pid != 0x02)
    {
        cError |= 1;
    }

    c6988CalibrationGet();

    ucConfig[0] = 0;
    ucConfig[1] = 0;
    ucConfig[2] = 0;
    ucConfig[3] = 0;
    cSoftIIC6998WriteDatas(IIC_6989_IC_ADDR, QMP6989_REG_CALIB00, ucConfig, 4);

    qmp6989_set_PP_OSR(QMP6989_P_OSR_4096);
    qmp6989_set_TT_OSR(QMP6989_T_OSR_1024);

    return cError;
}

int8_t c6988SoftReset(void)
{
    uint8_t ucConfig = 0x24;
    int8_t cError = 0, i = 0;

    cError |= cSoftIIC6998WriteDatas(IIC_6989_IC_ADDR, QMP6989_REG_RESET, &ucConfig, 1);

    for(i = 0; i < 64; ++i)
    {
        cError |= cSoftIIC6998ReadDatas(IIC_6989_IC_ADDR, QMP6989_REG_RESET, &ucConfig, 1);
        if((ucConfig & 1) == 0)
            break;

        vDelayMs(1);
    }

    if(ucConfig & 1)
    {
        cError |= 1;
    }

    return cError;
}

int8_t c6988StatusRead(void)
{
    uint8_t ucStatus = 0;
    int8_t cError = 0, i = 0;

    for(i = 0; i < 16; ++i)
    {
        cError = cSoftIIC6998ReadDatas(IIC_6989_IC_ADDR, QMP6989_REG_STATUS, &ucStatus, 1);

        if(((ucStatus & 0x0F) == 0x01) && (cError != 0))
            break;

        vDelayUs(1000);
    }

    if((ucStatus & 0x0F) != 0x01)
        cError |= 1;

    return cError;
}

/*!
 * @brief qmp6989 set pressure OSR
 *
 * @param osrP OSR to set
 *
 * @return Result from bus communication function
 * @retval -1 Bus communication error
 * @retval -127 Error null bus
 *
 */
int8_t qmp6989_set_PP_OSR(QMP6989_P_OSR_Type osrP)
{
    int8_t comRslt = 0, s8Tmp;
    uint8_t u8Data;

    //Read A6h
    s8Tmp = cSoftIIC6998ReadDatas(IIC_6989_IC_ADDR, QMP6989_REG_CONFIG2, &u8Data, 1);

    //Set the A6h[2:0] OSR bits
    u8Data = QMP6989_SET_BITSLICE(u8Data, QMP6989_P_OSR, osrP);
    s8Tmp = cSoftIIC6998WriteDatas(IIC_6989_IC_ADDR, QMP6989_REG_CONFIG2, &u8Data, 1);

    return comRslt;
}


/*!
 * @brief qmp6989 set temperature OSR
 *
 * @param osrT OSR to set
 *
 * @return Result from bus communication function
 * @retval -1 Bus communication error
 * @retval -127 Error null bus
 *
 */
int8_t qmp6989_set_TT_OSR(QMP6989_T_OSR_Type osrT)
{
    int8_t comRslt = 0, s8Tmp;
    uint8_t u8Data;

    //Read A7h
    s8Tmp = cSoftIIC6998ReadDatas(IIC_6989_IC_ADDR, QMP6989_REG_CONFIG3, &u8Data, 1);

    //Set the A7h[2:0] OSR bits
    u8Data = QMP6989_SET_BITSLICE(u8Data, QMP6989_T_OSR, osrT);
    s8Tmp = cSoftIIC6998WriteDatas(IIC_6989_IC_ADDR, QMP6989_REG_CONFIG3, &u8Data, 1);

    return comRslt;
}

int8_t c6988CalibrationGet(void)
{
    int16_t usCalibration = 0;
    uint8_t ucDatas[QMP6989_CALIBRATION_COUNT] = {0};
    int8_t cError = 0, i = 0;

    cError = cSoftIIC6998ReadDatas(IIC_6989_IC_ADDR, QMP6989_REG_CALIB00, ucDatas, QMP6989_CALIBRATION_COUNT);
    if(cError == 0)
    {
        for(i = 0; i < QMP6989_CALIBRATION_COUNT; ++i)
        {
            usCalibration = ((uint16_t)ucDatas[i *  2] + ucDatas[i * 2 + 1]);
            g_typeQMP6989Info.calibration[i] = usCalibration / 4.0f;
            g_typeQMP6989Info.calibration[i] *= QMP6989_POWER_SCALE[(ucDatas[2 * i + 1] & 0x03)] * QMP6989_CALIB_SCALE_FACTOR[i];
        }
    }

    return cError;
}

float f6988ReadTemperature(void)
{
    float fTemperature = 0.0f;
    uint8_t ucByte[2] = {0};

    // if(g_typeQMP6989Info.pid != 0x02)
    //     return 0.0f;

    ucByte[0] = 0x00;
    cSoftIIC6998WriteDatas(IIC_6989_IC_ADDR, QMP6989_REG_CONFIG1, ucByte, 1);
    ucByte[0] = 0x08;
    cSoftIIC6998WriteDatas(IIC_6989_IC_ADDR, QMP6989_REG_CMD, ucByte, 1);

    if(c6988StatusRead() == 0)
    {
        cSoftIIC6998ReadDatas(IIC_6989_IC_ADDR, QMP6989_REG_TEMPERATURE, ucByte, 2);

        fTemperature = (int16_t)((((uint16_t)ucByte[0]) << 8) + ucByte[1]) / 256.0f;
        g_typeQMP6989Info.temperatureF = fTemperature;

        /* 华氏度 转 摄氏度 */
        fTemperature = (fTemperature - 32.0f) / 1.8f;
        g_typeQMP6989Info.temperatureC = fTemperature;
    }

    return g_typeQMP6989Info.temperatureC;
}

int32_t i6988ReadPressure(void)
{
    int32_t iPressure = 0, iTemperature = 0;
    uint8_t ucPressure[4] = {0};
    uint8_t ucByte = 0;

    // if(g_typeQMP6989Info.pid != 0x02)
    //     return 0;

    /* 校准需要温度数据 */
    f6988ReadTemperature();

    ucByte = 0x02;
    cSoftIIC6998WriteDatas(IIC_6989_IC_ADDR, QMP6989_REG_CONFIG1, (uint8_t *)&ucByte, 1);
    ucByte = 0x09;
    cSoftIIC6998WriteDatas(IIC_6989_IC_ADDR, QMP6989_REG_CMD, (uint8_t *)&ucByte, 1);

    if(c6988StatusRead() == 0)
    {
        cSoftIIC6998ReadDatas(IIC_6989_IC_ADDR, QMP6989_REG_PRESSURE, ucPressure, 3);

        iPressure = (int32_t)(((uint32_t)ucPressure[2] << 24) | ((uint32_t)ucPressure[1] << 16) | (uint32_t)ucPressure[0] << 8);
        iPressure /= 256;

#if 1
        iTemperature = g_typeQMP6989Info.temperatureF * 256.0f;

        g_typeQMP6989Info.pressure = \
        g_typeQMP6989Info.calibration[0] + \
        g_typeQMP6989Info.calibration[1] * iTemperature + \
        g_typeQMP6989Info.calibration[2] * iTemperature * iTemperature + \
        g_typeQMP6989Info.calibration[3] * iPressure + \
        g_typeQMP6989Info.calibration[4] * iTemperature * iPressure + \
        g_typeQMP6989Info.calibration[5] * iTemperature * iTemperature * iPressure + \
        g_typeQMP6989Info.calibration[6] * iPressure * iPressure + \
        g_typeQMP6989Info.calibration[7] * iTemperature * iPressure * iPressure + \
        g_typeQMP6989Info.calibration[8] * iTemperature * iTemperature * iPressure * iPressure;

#else
        g_typeQMP6989Info.pressure = iPressure;

#endif
    }

    return g_typeQMP6989Info.pressure;
}

